package mx.com.sinformex.chat.core.client.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.Socket;
import java.net.SocketTimeoutException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import mx.com.sinformex.chat.core.client.IChatClient;
import mx.com.sinformex.chat.core.server.IChatRoom;
import mx.com.sinformex.chat.core.server.IChatServer;
import mx.com.sinformex.chat.core.utils.Message;

/**
 * The request message will be :
 * 
 * 
 * <simbel-chat><request type='type' source='client' source-ip='client ip' source-time='timestamp' message='' room='' /></simbel-chat>
 * 
 * And response will be :
 * 
 * <simbel-chat><response type='type' source='client' source-ip='client ip' source-time='timestamp' message='' room='' /></simbel-chat>
 * 
 * @author Oscar Ivan Hernandez Ventura [ oscar at sinformex dot com dot mx]
 *
 * @version $ Id : ChatClient.java , v 1.0 Aug 13, 2009 angellore $
 */
public class ChatClient implements IChatClient {

	private Socket socket;
	private InputStream in = null;
	private OutputStream out = null;
	private IChatServer server;
	private boolean run = false;

	public ChatClient(Socket s, IChatServer server) {
		this.socket = s;
		this.server = server;

		try {
			in = socket.getInputStream();
			out = socket.getOutputStream();
			run = true;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void run() {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		InputSource is = new InputSource();
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e1) {
			e1.printStackTrace();
		}


		try {
			while(run) {
				Message message = new Message();
				BufferedReader reader = new BufferedReader(new InputStreamReader(in));
				String xml = "";

				while((xml = reader.readLine()) != null) {
					is.setCharacterStream(new StringReader(xml.trim()));
					Document doc = null;
					try {
						doc = db.parse(is);
					} catch(SAXParseException ex) {
						continue;
					}
					NodeList nodes = doc.getElementsByTagName("request");	


					for (int i = 0; i < nodes.getLength(); i++) {
						Element element = (Element) nodes.item(i);
						String type = element.getAttribute("type");

						if(Integer.parseInt(type) == IChatClient.REQUEST_TYPE_ECHO) {
							out.write(response(IChatClient.RESPONSE_TYPE_ECHO, message).getBytes());
						} else if(Integer.parseInt(type) == IChatClient.REQUEST_TYPE_REQUEST_AVAILABLE_ROOMS) {
							StringBuilder buffer = new StringBuilder();
							for(IChatRoom room : server.getRooms()) {
								buffer.append(String.format("<room enable='%s' name='%s' max='%d' total='%d' />", false, "room", 10, 1));
								message.setMessage(buffer.toString());
								out.write(response(IChatClient.RESPONSE_TYPE_REQUEST_AVAILABLE_ROOMS, message).getBytes());
							}
						}
					}
					
					out.flush();
				}
			}


		} catch (SAXException e) {
			e.printStackTrace();
			run = false;
		} catch (IOException e) {
			e.printStackTrace();
			run = false;
		} catch (Exception e) {
			e.printStackTrace();
			run = false;
		} finally {
			if(!run) {
				try {
					in.close();
					out.close();						
					socket.close();
				} catch (IOException e) {
				}					
			}
		}
	}

	private String response(int response, Message message) {
		return String.format("<simbel-chat><response type='%d' source='%s' source-ip='%s' source-time='%s' message='%s' room='%s' />%s</simbel-chat>", response, message.getSource(), null, System.currentTimeMillis(), "echo", "room", message.getMessage());
	}

}
